package com.undsf.despot.modles;

import com.thoughtworks.xstream.XStream;
import com.undsf.despot.templates.impl.MonsterTemplateXml;
import com.undsf.despot.templates.BuffTemplateBase;
import com.undsf.despot.templates.ItemTemplateBase;
import com.undsf.despot.templates.MonsterTemplateBase;
import com.undsf.despot.templates.SkillTemplateBase;
import com.undsf.utility.Forest;
import com.undsf.utility.Node;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Arathi on 2016/10/3.
 */
public class Metadata {
    protected static Metadata CommonMetadata;

    protected List<MonsterTemplateBase> monsters;
    protected List<SkillTemplateBase> skills;
    protected List<ItemTemplateBase> items;
    protected List<BuffTemplateBase> buffs;

    public Forest skillTrees;
    public Map<Integer, MonsterTemplateBase> monsterDict;
    public Map<String, BuffTemplateBase> buffDict;
    public Map<String, ItemTemplateBase> itemDict;

    public static Metadata GetDefault() {
        Metadata metadata = new Metadata();
        metadata.monsters = new ArrayList<>();
        metadata.skills = new ArrayList<>();
        metadata.items = new ArrayList<>();
        metadata.buffs = new ArrayList<>();
        return metadata;
    }

    public static Metadata GetCommonMetadata() {
        if (CommonMetadata == null) {
            System.err.println("");
            CommonMetadata = GetDefault();
        }
        return CommonMetadata;
    }

    public static Metadata LoadFromXml(String xml, boolean setAsCommon) {
        XStream xs = new XStream();
        xs.alias("metadata", Metadata.class);
        xs.alias("monster", MonsterTemplateXml.class);
        xs.alias("skill", SkillTemplateBase.class);
        xs.alias("buff", BuffTemplateBase.class);
        xs.alias("item", ItemTemplateBase.class);
        xs.alias("skill_id", String.class);

        xs.autodetectAnnotations(true);//自动检测注解

        Metadata metadata = (Metadata)xs.fromXML(xml);

        Forest skillTrees = new Forest();
        for (SkillTemplateBase skill : metadata.skills) {
            Node node = new Node(skill.getId(), skill.getParent(), skill);
            skillTrees.addNode(node);
        }
        skillTrees.build();
        List<Node> skillNodes = skillTrees.toDfsList();
        for (Node skillNode : skillNodes) {
            SkillTemplateBase skill = (SkillTemplateBase) skillNode.referrer;
            if (skill.getParent() != null && !skill.getParent().isEmpty()) {
                SkillTemplateBase parent = (SkillTemplateBase) skillTrees.getNode(skill.getParent()).referrer;
                skill.inherit(parent);
            }
        }
        metadata.skillTrees = skillTrees;

        metadata.monsterDict = new HashMap<>();
        for (MonsterTemplateBase tpl : metadata.monsters) {
            MonsterTemplateXml xmlTpl = (MonsterTemplateXml) tpl;
            xmlTpl.convert();
            metadata.monsterDict.put(tpl.getID(), xmlTpl);
        }

        metadata.buffDict = new HashMap<>();
        for (BuffTemplateBase tpl : metadata.buffs) {
            metadata.buffDict.put(tpl.id, tpl);
        }

        // TODO 初始化itemDict

        if (setAsCommon) CommonMetadata = metadata;
        return metadata;
    }

    public Monster createMonster(int id) {
        MonsterTemplateBase monsterTpl = monsterDict.get(id);
        return monsterTpl.create();
    }

    public Skill createSkill(String id) {
        try {
            Node skillNode = skillTrees.getNode(id);
            SkillTemplateBase skillTpl = (SkillTemplateBase) skillNode.referrer;
            return skillTpl.create();
        }
        catch (Exception ex) {
            System.err.println("创建技能'" + id +"'" + "时报错");
            ex.printStackTrace();
        }
        return null;
    }

    public Item createItem(String id) {
        return null;
    }

    public Buff createBuff(String id) {
        BuffTemplateBase buffTpl = buffDict.get(id);
        return buffTpl.create();
    }
}
